home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’96 / Booting Gallery / Booting Gallery (source) / Sources / Sprite Sources / Sprite.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-22  |  7.0 KB  |  424 lines  |  [TEXT/BROW]

  1. #include "sprite.h"
  2. #include <globals.h>
  3. #include "stallowdraw.h"
  4.  
  5. static short    GetMainSlot()
  6. {
  7.     short    mainDeviceRefNum = GetMainDevice()[0]->gdRefNum;
  8.     short    mainSlotNumber = AuxDCEHandle(GetDCtlEntry(mainDeviceRefNum))[0]->dCtlSlot;
  9.     
  10.     return mainSlotNumber;
  11. }
  12.  
  13. inline short RectHeight(const Rect& r)
  14. {
  15.     return r.bottom - r.top;
  16. }
  17.  
  18. inline short RectWidth(const Rect& r)
  19. {
  20.     return r.right - r.left;
  21. }
  22.  
  23. CSprite::CSprite(CSpriteWorld* theWorld,long id,const Rect& inStart)
  24.     :    fLocation(inStart),
  25.         fID(id),
  26.         fWorld(theWorld)
  27. {
  28.     fWorld->AddSprite(this);
  29. }
  30.  
  31.  
  32.  
  33.  
  34.  
  35. CSprite::~CSprite()
  36. {
  37.     fWorld->RemoveSprite(this);
  38. }
  39.  
  40. const    Rect*            CSprite::GetGameBounds()
  41. {
  42.     return fWorld->GetSpriteCanvas()->GetBounds();
  43. }
  44.  
  45.  
  46. Boolean            CSprite::KeyIsDownQ(short k)
  47. {
  48.     unsigned char    km[16];
  49.     
  50.     GetKeys((UInt32*)km);
  51.     return (( (km[k>>3] >> (k & 7)) & 1) != 0);
  52. }
  53.  
  54.  
  55. Boolean            CSprite::OutOfBoundsQ()
  56. {
  57.     Rect            r;
  58.     
  59.     return !SectRect(&fLocation,GetGameBounds(),&r);
  60. }
  61.  
  62.  
  63. static Rect    make_rect(GWorldPtr gWorld,short startTop,short startLeft)
  64. {
  65.     Rect        r;
  66.     SetRect(&r,startLeft,startTop,startLeft,startTop);
  67.  
  68.     
  69.     return r;
  70. }
  71.  
  72. CPixMapSprite::CPixMapSprite(CSpriteWorld* world,long id,GWorldPtr image,
  73.                         short startTop,short startLeft,RgnHandle mask)
  74.     :    CSprite(world,id, make_rect(image,startTop,startLeft))
  75. {
  76.     SetImage(image,mask);
  77. }
  78.  
  79.  
  80. void    CPixMapSprite::Draw()//Override
  81.  
  82. {
  83.     if(fGWorld != NULL){
  84.         Rect        source = *GetLocation();
  85.         OffsetRect(&source,-source.left,-source.top);
  86.         GetWorld()->GetSpriteCanvas()->Blit(fPixMap, source, *GetLocation(), fSourceMask);
  87.     }
  88. }
  89.  
  90. void    CPixMapSprite::SetImage(GWorldPtr    image,RgnHandle mask)
  91. {
  92.     fGWorld = image;
  93.     fSourceMask = mask;
  94.     
  95.     if(fGWorld != NULL){
  96.         
  97.         fPixMap = GetGWorldPixMap(image);
  98.         LockPixels(fPixMap);
  99.         
  100.         PixMapState        pixMapState;
  101.         LockPixMap(fPixMap,pixMapState);
  102.     
  103.         Rect        imageSize = fPixMap[0]->bounds;
  104.         Rect*        me = GetLocation();
  105.         
  106.         me->right = me->left + RectWidth(imageSize);
  107.         me->bottom = me->top + RectHeight(imageSize);
  108.  
  109.     }
  110. }
  111.  
  112.  
  113. CPixMapSprite::~CPixMapSprite()//Override
  114.  
  115. {
  116.  
  117. }
  118.  
  119.  
  120.  
  121. CHPixMapSprite::CHPixMapSprite(CSpriteWorld* world,long id,GWorldPtr image,
  122.                         short startTop,short startLeft,RgnHandle mask)
  123.     :    CPixMapSprite( world,id, image, startTop, startLeft, mask)
  124. {
  125.     
  126. }
  127.  
  128.  
  129. void    CHPixMapSprite::UpdatePosition()//Override
  130. {
  131.     OffsetRect(GetLocation(),5,0);
  132.     if(GetLocation()->left > GetWorld()->GetSpriteCanvas()->GetBounds()->right){
  133.         new CHPixMapSprite(GetWorld(), 0, fGWorld, GetLocation()->top+50, 0, NULL);
  134.         delete this;
  135.     }
  136. }
  137.  
  138. CHPixMapSprite::~CHPixMapSprite()//Override
  139.  
  140. {
  141.  
  142. }
  143.  
  144.  
  145.  
  146. void        CSpriteCanvas::Blit(PixMapHandle pm,
  147.                             const Rect& inSourceRect,
  148.                             const Rect& inDestRect,
  149.                             RgnHandle inSourceMask)
  150. {
  151.     GWorldPtr        saveGWorld;
  152.     GDHandle        saveGD;
  153.     
  154.     ::GetGWorld(&saveGWorld,&saveGD);
  155.     SetGWorld(fGWorld,NULL);
  156.     
  157.     if(inSourceMask != NULL){
  158.         OffsetRgn(inSourceMask,inDestRect.left,inDestRect.top);
  159.     }
  160.     
  161.     CopyBits((BitMap*)*pm, (BitMap*)*fPixMap, &inSourceRect, &inDestRect, srcCopy, inSourceMask);
  162.     
  163.     if(inSourceMask != NULL){
  164.         OffsetRgn(inSourceMask,-inDestRect.left,-inDestRect.top);
  165.     }
  166.  
  167.     SetGWorld(saveGWorld,saveGD);
  168. }
  169.  
  170. void        CSpriteCanvas::PrepareToDraw()
  171. {
  172.     SetGWorld(fGWorld,NULL);
  173. }
  174.  
  175.  
  176.  
  177. CSpriteCanvas::~CSpriteCanvas()
  178. {
  179.     
  180. }
  181.  
  182.  
  183. CSpriteCanvas::CSpriteCanvas(OSErr& err)
  184. {
  185.     fGWorld = NULL;
  186.     GDHandle    device = GetMainDevice();
  187.     Rect        bounds = device[0]->gdRect;
  188.     err = NewGWorld(&fGWorld, 0,&bounds, NULL, NULL, 0);
  189.     if(err == noErr){
  190.         fPixMap = GetGWorldPixMap(fGWorld);
  191.         LockPixels(fPixMap);
  192.         
  193.         PixMapState        pixMapState;
  194.         LockPixMap(fPixMap,pixMapState);
  195.         fBounds = bounds;
  196.     
  197.     
  198.     }
  199. }
  200.  
  201.  
  202. void    CSpriteWorld::AddSprite(CSprite* sprite)
  203. {
  204.     fSpriteQueue.Enqueue(sprite);
  205. }
  206.  
  207.  
  208. void    CSpriteWorld::DrawAll()
  209. {
  210.     DrawBackground();
  211.     DrawSprites();
  212.     Rect        r = fCanvas->GetPixMap()[0]->bounds;
  213.     
  214.     StSaveGWorld        save;
  215.     
  216.     SetGWorld(fCanvas->GetGWorld(),NULL);
  217.     CopyBits((BitMap*)*fCanvas->GetPixMap(), (BitMap*)*fMainPixMap, &r, &r, srcCopy, NULL);    
  218. }
  219.  
  220.  
  221. void    CSpriteWorld::DrawBackground()
  222. {
  223.     Rect        source = *fBackground->GetBounds();
  224.     
  225.     fCanvas->Blit(fBackground->GetPixMap(),source, source, NULL);
  226. }
  227.  
  228.  
  229. void    CSpriteWorld::DrawSprites()
  230. {
  231.     TQIterator<CSprite>        iter(fSpriteQueue);
  232.     
  233.     while(iter.MoreQ()){
  234.         CSprite*    thisSprite = iter.GetNext();
  235.         
  236.         thisSprite->Draw();
  237.     }
  238. }
  239.  
  240.  
  241. void    CSpriteWorld::ImageBackground(CSpriteCanvas* canvas)
  242. {
  243.     StSaveGWorld        save;
  244.     
  245.     fBackground->PrepareToDraw();
  246.     BackColor(blackColor);
  247.     EraseRect(fBackground->GetBounds());
  248.     BackColor(whiteColor);
  249. }
  250.  
  251.  
  252. void    CSpriteWorld::Idle()
  253. {
  254.     UpdateSpriteLocations();
  255.     CheckForHits();
  256.     DrawAll();
  257. }
  258.  
  259.  
  260. CSpriteWorld::~CSpriteWorld()
  261. {
  262.     Stop();
  263.     RestorePixMap(fMainPixMap,fMainPixMapState);
  264.     HSetState((Handle)GetMainDevice(),fDeviceState);
  265. }
  266.  
  267.  
  268. void    CSpriteWorld::UpdateSpriteLocations()
  269. {
  270.     TQIterator<CSprite>        iter(fSpriteQueue);
  271.     
  272.     while(iter.MoreQ()){
  273.         CSprite*        thisOne = iter.GetNext();
  274.         
  275.         thisOne->UpdatePosition();
  276.     }
  277. }
  278.  
  279.  
  280. CSpriteWorld::CSpriteWorld(OSErr&    err)
  281. {
  282.     err = noErr;
  283.     fVBLInstalledQ = false;
  284.     
  285.     GDHandle    device = GetMainDevice();
  286.     fDeviceState = HGetState((Handle)device);
  287.     HLock((Handle)device);
  288.     fMainPixMap = device[0]->gdPMap;
  289.     LockPixMap(fMainPixMap,fMainPixMapState);
  290.     // lock it here
  291.     
  292.     fCanvas = new CSpriteCanvas(err);
  293.     if(err == noErr){
  294.         fBackground = new CSpriteCanvas(err);
  295.         if(err == noErr){
  296.             ImageBackground(fBackground);
  297.         }    
  298.     }
  299.     
  300. }
  301.  
  302. void    CSpriteWorld::_VBLTask()
  303. {
  304.     ExtendedVBL*        pb;
  305.     long                saveGlobals;
  306.     short                oldMemError = *(short *)0x220;
  307.  
  308.     pb = (ExtendedVBL*)GetA0();
  309.     saveGlobals = GET_GLOBALS();
  310.     
  311.     SET_GLOBALS(pb->saveGlobals);
  312.     StAllowDraw            allowDraw;
  313.  
  314.     long        oldA5 = pb->thisObj->fA5World.Use();
  315.     
  316.     pb->thisObj->Idle();
  317.     
  318.     pb->thisObj->fA5World.Restore(oldA5);
  319.     
  320.     // ##HACK##
  321. #ifdef __G_A4__
  322.     if(LMGetCurApRefNum() <= 0){
  323. #endif
  324.         pb->vblCount = kInterval;
  325. #ifdef __G_A4__
  326.     }
  327. #endif
  328.  
  329.     *(short *)0x220 = oldMemError;
  330.     SET_GLOBALS(saveGlobals);
  331. }
  332.  
  333.  
  334. void    CSpriteWorld::InstallVBL()
  335. {
  336.     if(!fVBLInstalledQ){
  337.         fVBLInstalledQ = true;
  338.         
  339.         fVBL.qType = 1;
  340.         fVBL.vblAddr = (VBLUPP)_VBLTask;
  341.         fVBL.vblCount = kInterval;
  342.         fVBL.vblPhase = 0;
  343.         fVBL.saveGlobals = GET_GLOBALS();
  344.         fVBL.thisObj = this;
  345.         
  346.         SlotVInstall((QElemPtr)&fVBL,GetMainSlot());
  347.     }
  348. }
  349.  
  350.  
  351. void    CSpriteWorld::RemoveVBL()
  352. {
  353.     if(fVBLInstalledQ){
  354.         fVBLInstalledQ = false;
  355.         SlotVRemove((QElemPtr)&fVBL,GetMainSlot());
  356.     }
  357. }
  358.  
  359. void            CSpriteWorld::CheckForHits()
  360. {
  361.     TQIterator<CSprite>        iter(fSpriteQueue);
  362.     
  363.     while(iter.MoreQ()){
  364.         CSprite*    thisOne = iter.GetNext();
  365.         
  366.         CheckForHitsOnThisSprite(thisOne);
  367.     }
  368. }
  369.  
  370.  
  371. void            CSpriteWorld::CheckForHitsOnThisSprite(CSprite*    thisOne)
  372. {
  373.     TQIterator<CSprite>        iter(fSpriteQueue);
  374.     Rect*                    r1;
  375.     Rect*                    r2;
  376.     Rect                    r3;
  377.     
  378.     r1 = thisOne->GetLocation();
  379.     while(iter.MoreQ()){
  380.         CSprite*    test = iter.GetNext();
  381.         
  382.         if(test != thisOne){
  383.             r2 = test->GetLocation();
  384.             if(SectRect(r1,r2,&r3)){
  385.                 if(!test->WasHitBy(thisOne)){
  386.                     break;
  387.                 }
  388.             }
  389.         }
  390.     }
  391. }
  392.  
  393.  
  394. void            CSpriteWorld::RemoveSprite(CSprite* sprite)
  395. {
  396.     fSpriteQueue.Dequeue(sprite);
  397. }
  398.  
  399.  
  400. void            CSpriteWorld::Start()
  401. {
  402.     InstallVBL();
  403. }
  404.  
  405.  
  406. void            CSpriteWorld::Stop()
  407. {
  408.     RemoveVBL();
  409. }
  410.  
  411.  
  412.  
  413.  
  414. StSaveGWorld::StSaveGWorld()
  415. {
  416.     GetGWorld(&fSaveGWorld,&fSaveGD);
  417. }
  418.  
  419.  
  420. StSaveGWorld::~StSaveGWorld()
  421. {
  422.     SetGWorld(fSaveGWorld,fSaveGD);
  423. }
  424.